package mebp.genetic.mutation;

import mebp.genetic.Individuum;
import mebp.genetic.Population;

import org.apache.log4j.Logger;

public class SimpleMutation implements MutationStrategy {

	Logger log = Logger.getLogger(SimpleMutation.class);
	private double probability;
	private Boolean keepBadMutations;
	private int mutationStrength;
	
	public void setMutationStrength(int mutationStrength) {
		this.mutationStrength = mutationStrength;
	}
	
	public SimpleMutation(double probability, Boolean keepBadMutations) {
		this.probability = probability;
		this.keepBadMutations = keepBadMutations;
		this.mutationStrength = 1;
	}
	
	public void mutate(Population population) {
		//int imp = 0;
		
		//Mutation based on population size
		final int mutants = (int)Math.round(population.getSize()*probability);
		final int mutate = population.getSize()/mutants;
		int count = 0;
		
		for (Individuum i:population)  {
			count++;
			if (count>=mutate) {
				
				Individuum iold = null;
				if (!keepBadMutations) {
					iold = (Individuum)i.clone();
				}
				i.optimizeLightAndCheck();
			
				int elem = (int)Math.round(Math.random()*(i.genom.length-1));
		
					if (i.genom[elem] >= mutationStrength+1) {
						// decrement
						i.genom[elem] = i.genom[elem] - mutationStrength;
					} else {
						// increment
						i.genom[elem] = i.genom[elem] + mutationStrength;
					}
				i.invalidateCache();
				i.repair();
				
				if (!keepBadMutations) {
					double before=iold.getFitness();
					double after = i.getFitness();
					// float improvement =
					// (Math.round((after/before-1)*10000)/100f)*-1;
					if (after < before) {
						log
								.debug("Mutation improved Fitness by "
										+ (Math
												.round((after / before - 1) * 10000) / 100f)
										* -1 + "%");
					} else {
						i = iold;
					}
				}

				count = 0;
			}
		}
	}

}
